home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / math / gle-3.000 / gle-3 / gle / util / manip / cmd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-07  |  27.9 KB  |  1,260 lines

  1. /*  number    - put it in current cell and move in current dir
  2.     'string   - put string in cell and move in current direction
  3.     range = expression  - evaluate exp for each cell in range
  4.     cell(exp,exp) = expression  - evaluate exp and put in cell
  5.     cmd - exectue command, if then else next for save load generate
  6.                    print, input
  7.     & = continued on next line.
  8.  
  9.     load b.dat  range c3r3   width 10.3  between ", "
  10.     save b.c  c3c4
  11.     set outwidth 0
  12.     set outwidth 10.3
  13.     set between ", "
  14.     copy c1 c2
  15. */
  16.  
  17. #include "all.h"
  18. #include <math.h>
  19. #include <time.h>
  20. #include "edt.h"
  21. #include "keyword.h"
  22. int range_next(RANGE *r);
  23. int range_def(char *s, RANGE *r);
  24. int sort_shuffle(int i, int r1, int *pnt);
  25. int m_tokinit(char *termset);
  26. int passcmd(char *source,char *tk[],int *ntok);
  27. int do_assign(char *t1, char *t2);
  28. extern int in_recover;
  29. extern int curx;
  30. extern int cury;
  31. extern int max_x,max_y;
  32. #define tok(j) (tk[j])
  33. #define dbg if (gle_debug>0)
  34. extern char file_name[];
  35. extern int iserr;
  36. extern int gle_debug,changed;
  37. extern int trace_on;
  38. extern int exit_manip;
  39. int isating;
  40. int islogging;
  41. int load_list;
  42. int dpoints[200];
  43. int coltype[200];
  44. int outwidth1=8,outwidth2=8;
  45. char *between=" ";
  46. char strmiss[40];
  47. /*---------------------------------------------------------------------------*/
  48. do_command(char *cmd)
  49. {
  50.     static char inbuff[200];
  51.     static char *tk[500];
  52.     static char tkbuff[500];
  53.     int j,i,al,ntok,f;
  54.     static char space_str[] = " ";
  55.  
  56.     if (islogging) log_write(cmd);
  57.     
  58.     token_space();
  59.     strcat(inbuff,cmd);
  60.     al = strlen(inbuff);
  61.     if (inbuff[al-1]=='&') {
  62.         inbuff[al-1] = 0;
  63.         return;
  64.     }
  65.     token(inbuff,tk,&ntok,tkbuff);
  66.     for (i=ntok+1;i< ntok+5;i++) tk[i] = space_str;
  67. /*   for (i=1;i<=ntok;i++) printf("token{%s} ",tk[i]);
  68.      printf("\n"); */
  69.     passcmd(inbuff,tk,&ntok);
  70.     inbuff[0] = 0;
  71.  
  72. }
  73.  
  74. extern int moving_x, moving_y;
  75.  
  76.  
  77. passcmd(char *source,char *tk[],int *ntok)
  78. {
  79.     int j,etype,sub_start,sub_end,i,f,np,ix,vidx,vtype=1;
  80.     double v;
  81.     char *sp;
  82.     etype = 1;
  83.     find_mkey(tok(1),&ix);
  84.     if (strcmp(tok(2),"=")==0)  {
  85.         do_assign(tok(1),tok(3));
  86.         return;
  87.     }
  88.     sp = strchr(tok(1),'=');
  89.     if (sp!=NULL) {
  90.         *sp = 0;
  91.         do_assign(tok(1),sp+1);
  92.         return;
  93.     }
  94.     if (isnumber(tok(1)) || *tok(1)=='-') {
  95.         set_cell(curx,cury,atof(tok(1)));
  96.         set_newxy(curx+moving_x,cury+moving_y);
  97.         return;
  98.         }
  99.     if ((*tok(1))=='"') {
  100.         *(tok(1)+strlen(tok(1))-1) = 0;
  101.         set_scell(curx,cury,tok(1)+1);
  102.         set_newxy(curx+moving_x,cury+moving_y);
  103.         return;
  104.         }
  105.     if ((*tok(1))=='@') {
  106.         at_open(tok(1)+1);
  107.         return;
  108.     }
  109.     switch (ix) {
  110.       case k_data: /* data <range> */
  111.         cmd_data(tok(2));
  112.         break;
  113.       case k_help:/* help load */
  114.         if (*ntok==1) do_help("MANIP","");
  115.         else do_help(tok(2),tok(3));
  116.         refresh();
  117.         break;
  118.       case k_list: /* list a.a [range] , reads a list of numbers */
  119.         load_list = true;
  120.         cmd_load(tok(2),tok(3),*ntok);
  121.         load_list = false;
  122.         break;
  123.       case k_load: /* LOAD  A.A  [range] -LIST */
  124.         if (*ntok>3) if (strcmp(tok(4),"-LIST")==0) load_list = true;
  125.         cmd_load(tok(2),tok(3),*ntok);
  126.         load_list = false;
  127.         break;
  128.       case k_save: /* SAVE [a.a] [range] [format-string] */
  129.         changed = false;
  130.         cmd_save(tok(2),tok(3),tok(4),*ntok);
  131.         break;
  132.       case k_set: /* set outwidth, set width, set between, */
  133.         if (strcmp(tok(2),"OUTWIDTH")==0) set_outwidth(tok(3));
  134.         else if (strcmp(tok(2),"WIDTH")==0) set_outwidth(tok(3));
  135.         else if (strcmp(tok(2),"BETWEEN")==0) between = unquote(tok(3));
  136.         else if (strcmp(tok(2),"MISSING")==0) strcpy(strmiss,unquote(tok(3)));
  137.         else if (strcmp(tok(2),"DIGITS")==0) outwidth2 = atoi(tok(3));
  138.         else if (strcmp(tok(2),"DPOINTS")==0) {
  139.             i = atoi(tok(3));
  140.             if (*ntok>3) dpoints[atoi(tok(4))] = i;
  141.             else for (j=0;j<200;j++) dpoints[j] = i;
  142.         }
  143.         else if (strcmp(tok(2),"COLTYPE")==0) {
  144.             i = atoi(tok(3));
  145.             if (*tok(3)=='C') i = atoi(tok(3)+1);
  146.             if (strcmp(tok(4),"BOTH")==0) j = 0;
  147.             if (strcmp(tok(4),"DECIMAL")==0) j = 1;
  148.             if (strcmp(tok(4),"EXP")==0) j = 2;
  149.             if (strcmp(tok(4),"DPOINTS")==0) {
  150.                 j = atoi(tok(5));
  151.                 if (i==0) for (i=0;i<200;i++) dpoints[i] = j;
  152.                 else dpoints[i] = j;
  153.             } else {
  154.                 if (i==0) for (i=0;i<200;i++) coltype[i] = j;
  155.                 else coltype[i] = j;
  156.             }
  157.         }
  158.         else if (strcmp(tok(2),"COLUMNS")==0) set_ncol(atoi(tok(3)));
  159.         else if (strcmp(tok(2),"NCOL")==0) set_ncol(atoi(tok(3)));
  160.         else if (strcmp(tok(2),"COLWIDTH")==0) set_colwidth(atoi(tok(3)));
  161.         else if (strcmp(tok(2),"PRECISION")==0) outwidth2 = atoi(tok(3));
  162.         else if (strcmp(tok(2),"SIZE")==0) {
  163.             set_size(atoi(tok(3)),atoi(tok(4)));
  164.         }
  165.         else fner("Invalid SET command, Use (width,between,digits,dpoints,ncol,colwidth)\n");
  166.         break;
  167.       case k_new: /* clears the spreadsheet and free's memory */
  168.         clear_data();
  169.         break;
  170.       case k_clear: /* clear part of the spread sheet */
  171.         cmd_clear(tok(2));
  172.         break;
  173.       case k_delete: /* delete <range> [if <exp>] */
  174.         cmd_delete(tok(2),tok(4),*ntok);
  175.         trim_data();
  176.         break;
  177.       case k_insert: /* insert <range> */
  178.         cmd_insert(tok(2));
  179.         break;
  180.       case k_exit:
  181.         cmd_save(tok(2),tok(3),tok(4),*ntok);
  182.         changed = false;
  183.         exit_manip = true;
  184.         break;
  185.       case k_quit:
  186.         exit_manip = true;
  187.         break;
  188.       case k_logging: /* log filename */
  189.         if (islogging) log_close();
  190.         log_open(tk[2]);
  191.         break;
  192.       case k_close:
  193.         log_close();
  194.         break;
  195.       case k_at: /* execute file of manip commands */
  196.         at_open(tk[2]);
  197.         break;
  198.       case k_call:
  199.         refresh();
  200.         break;
  201.       case k_sort: /* sort <range> on <exp> */
  202.         cmd_sort(tk[2],tk[4],*ntok);
  203.         break;
  204.       case k_swap: /* swap CaCb  || swap RaRb */
  205.         cmd_swap(tk[2]);
  206.         break;
  207.       case k_shell:
  208.         window(1,1,80,25); scr_norm(); clrscr();
  209.         printf("Type in EXIT to return to MANIP\n\n");
  210.         #ifndef DJ    /* a.r. */
  211.         system("");
  212.         #else
  213.         system(getenv("COMSPEC"));
  214.         #endif
  215.         refresh();
  216.         break;
  217.       case k_sum:
  218.         cmd_sum(tk[2]);
  219.         break;
  220.       case k_fit:
  221.         cmd_fit(tk[2]);
  222.         break;
  223.       case k_parsum:
  224.         cmd_parsum(tk[2],tk[3]);
  225.         break;
  226.       case k_if:
  227.       case k_else:
  228.       case k_end:
  229.       case k_for:
  230.       case k_next:
  231.       case k_print:
  232.       case k_input: /* input "prompt" variable */
  233.       case k_copy: /* copy range1  range2  [if exp] (doesn't) */
  234.         cmd_copy(tk[2],tk[3],tk[5],*ntok,true);
  235.         break;
  236.       case k_move: /* move range1  range2  [if exp] (leaves gaps) */
  237.         cmd_copy(tk[2],tk[3],tk[5],*ntok,false);
  238.         break;
  239.       case k_prop: /* prop range1  range2  (cycle thru range1)  */
  240.         cmd_copy(tk[2],tk[3],tk[5],*ntok,2);
  241.         break;
  242.       case k_generate: /* gen 2(1,2:4)3  c1  (1 1 2 2 3 3 4 4) 3 times*/
  243.         cmd_generate(tk[2],tk[3],*ntok);
  244.         break;
  245.       case k_let:
  246.         /* let variable = expression */
  247.         var_findadd(tk[2],&vidx,&vtype);
  248.         evaluate(tk[4],&v);
  249.         var_set(vidx,v);
  250.         break;
  251.       case k_goto: /* should really use eval, not atoi so var's work */
  252.         set_newxy(atoi(tk[2]),atoi(tk[3]));
  253.         break;
  254.       default:
  255.         fner("No such command {%s} {%s}\n",tk[1],tk[2]);
  256.     }
  257. }
  258. struct op_key { char *name; int typ; int pos; int32 idx; } ;
  259. typedef struct op_key (*OPKEY)[100];
  260.  
  261.  
  262. do_assign(char *t1, char *t2)
  263. {
  264.     RANGE rr;
  265.     int cp,vtype,vidx;
  266.     double v;
  267.     static int32 pcode[200];
  268.     static char outstr[80];
  269.     int plen;
  270.     vtype = 1;
  271.  
  272.         /* ------------------       */
  273.         /* variable = expression    */
  274.         /* cell(exp,exp) = exp      */
  275.         /* range = exp          */
  276.         /* ------------------       */
  277.  
  278.     if (strncmp(t1,"CELL(",5)==0) {     /* cell(exp,exp) = exp */
  279.       {     char s1[80],s2[80],*s;
  280.         int x,y;
  281.         s = strchr(t1,',');
  282.         if (s==NULL) {
  283.             fner("Expecting CELL(EXP,EXP) = EXP \n");
  284.             return;
  285.         }
  286.         strcpy(s1,t1+5); strcpy(s2,s+1);
  287.         *strchr(s1,',') = 0;
  288.         if (strchr(s2,')')!=NULL) *strchr(s2,')') = 0;
  289.         evaluate(s1,&v); x = v;
  290.         evaluate(s2,&v); y = v;
  291.         evaluate(t2,&v);
  292.         set_cell(x,y,v);
  293.         show_ifcell(x,y);
  294.       }
  295.       return;
  296.     }
  297.     if (range_def(t1,&rr)) {                /* range = exp */
  298.      {
  299.        int c_idx[20], c_val[20], nc, j;
  300.        int r_idx[20], r_val[20], nr;
  301.  
  302.         polish(t2,(char *) pcode,&plen,&vtype);
  303.         var_find_rc(c_idx,c_val,&nc,'C');
  304.         var_find_rc(r_idx,r_val,&nr,'R');
  305.         for (;range_next(&rr);) {
  306.             cp = 0;
  307.             eval_setxy(rr.col,rr.row);
  308.             for (j=0;j<nc;j++) {
  309.                 var_set(c_idx[j],vcell(c_val[j],rr.row));
  310.             }
  311.             for (j=0;j<nr;j++) {
  312.                 var_set(r_idx[j],vcell(rr.col,r_val[j]));
  313.             }
  314.             eval(pcode,&cp,&v,outstr,&vtype);
  315.             set_cell(rr.col,rr.row,v);
  316.             show_ifcell(rr.col,rr.row);
  317.         }
  318.         return;
  319.      }
  320.     }
  321.     fner("error, expecting cell(exp,exp) = exp, or range = exp \n");
  322. }
  323. evaluate(char *exp, double *v)
  324. {
  325.     static int32 pcode[200];
  326.     int plen,vtype,cp;
  327.     static char outstr[100];
  328.  
  329.     vtype = 1;
  330.     polish(exp,(char *) pcode,&plen,&vtype);
  331.     if (plen>150) fner("pcode too int32, report bug to Chris\n");
  332.     cp = 0;
  333.     eval(pcode,&cp,v,outstr,&vtype);
  334. }
  335. int new_line;
  336. range_next(RANGE *r)
  337. {
  338.     new_line = false;
  339.     if (r->row==0) {
  340.         r->row = r->r1; r->col = r->c1;
  341.         return true;
  342.     }
  343.     if (r->colfirst) {
  344.         r->col++;
  345.         if (r->col > r->c2) {
  346.             new_line = true;
  347.             r->col = r->c1;
  348.             r->row++;
  349.             if (r->row > r->r2) return false;
  350.         }
  351.     } else {
  352.         r->row++;
  353.         if (r->row > r->r2) {
  354.             new_line = true;
  355.             r->row = r->r1;
  356.             r->col++;
  357.             if (r->col > r->c2) return false;
  358.         }
  359.     }
  360.     return true;
  361. }
  362. range_def(char *sxx, RANGE *r)
  363. {
  364.   char s[80];
  365.     char *s1;
  366.     char rr,cc;
  367.   strcpy(s,sxx);
  368.     strip_colon(s);
  369.     r->c1 = r->c2 = r->r1 = r->r2 = r->row = r->col = 0;
  370.  
  371.     if (*s=='C') {cc='C'; rr='R'; r->colfirst = true;}
  372.     else if (*s=='R') {cc='R'; rr='C'; r->colfirst = false;}
  373.     else return false;
  374. /*  c1   c1r1r10   c3c4r7 c3r7  c3c4r1r2 |   r1r2c1c3   c3r7  r2*/
  375.  
  376.     s1 = range_int(s,&(r->c1));
  377.     if (*s1==cc) {
  378.         s1 = range_int(s1,&r->c2);
  379.     }
  380.     if (*s1==rr) {
  381.         s1 = range_int(s1,&r->r1);
  382.         if (*s1==cc) {
  383.             s1 = range_int(s1,&r->c2);
  384.         }
  385.         if (*s1==rr) {
  386.             s1 = range_int(s1,&r->r2);
  387.         }
  388.         if (*s1==cc) {
  389.             s1 = range_int(s1,&r->c2);
  390.         }
  391.     }
  392.     if (!r->colfirst) {
  393.         swapint(&r->c1,&r->r1);
  394.         swapint(&r->c2,&r->r2);
  395.     }
  396.     if (r->c1 == 0) r->c1 = 1;
  397.     if (r->c2 == 0) {
  398.       if (!r->colfirst) {
  399.         if (r->c1 > max_x) r->c2 = r->c1; else r->c2 = max_x;
  400.       } else {
  401.         r->c2 = r->c1;
  402.       }
  403.     }
  404.     if (r->r1 == 0) r->r1 = 1;
  405.     if (r->r2 == 0) {if (r->colfirst)
  406.         { if (r->r1>max_y) r->r2 = r->r1; else r->r2 = max_y;}
  407.       else r->r2 = r->r1;}
  408.  
  409. /*    printf("range def %d %d   %d %d  | \n",r->c1,r->r1,r->c2,r->r2); getch();*/
  410.     data_expand(r->c2,r->r2);
  411.     if (*s1!=0) return false;
  412.     return true;
  413. }
  414. char *range_int(char *s, int *v)
  415. {
  416.     static char buff[40],*b;
  417.     b = buff;
  418.     for (s++;*s!=0 && isdigit(*s);)
  419.         *b++ = *s++;
  420.     *b++ = 0;
  421.     *v = atoi(buff);
  422.     return s;
  423. }
  424. swapint(int *a, int *b)
  425. {
  426.     int c;
  427.     c = *a;
  428.     *a = *b;
  429.     *b = c;
  430. }
  431. char *sep_chars=", \t\n";
  432. cmd_load(char *fname, char *range, int ntok)
  433. {
  434.     RANGE rr;
  435.     static char inbuff[8001];
  436.     FILE *fptr;
  437.     int i;
  438.     
  439.     m_tokinit(sep_chars);
  440.  
  441.     if (ntok<2) fname = file_name;
  442.     strcpy(file_name,fname);
  443.  
  444.     if (ntok>2) {
  445.      if (range_def(range,&rr)) range_next(&rr);
  446.      else  {                /* range = exp */
  447.          fner("Invalid load range given (%s) \n",range);
  448.          return;
  449.      }
  450.     } else {
  451.      rr.col = 1;  rr.row = 1;
  452.     }
  453.     strlwr(fname);
  454.     fptr = fopen(fname,"r");
  455.     if (fptr==NULL) {
  456.         fner("Could not open (%s) \n",fname);
  457.         return;
  458.     }
  459.     for (;!feof(fptr);) {
  460.         if (fgets(inbuff,7000,fptr)!=NULL) {
  461.             if (load_list) cmd_load_list(&rr,inbuff);
  462.             else cmd_load_line(rr.col,rr.row++,inbuff);
  463.         }
  464.     }
  465.     fclose(fptr);
  466. }
  467.  
  468. static char term_table[256];
  469. m_tokinit(char *termset)
  470. {
  471.     int i;
  472.     for (i=0;i<=255;i++) {
  473.         if (strchr(termset,i)!=NULL) 
  474.             term_table[i]=true;
  475.         else  term_table[i]=false;
  476.     }
  477. }
  478. char *m_tokend(char *s);
  479. char *m_tokend(char *s)
  480. {
  481.     static char *p1,*p2,*ss,*p,savechar;
  482.     if (s!=NULL) {
  483.         ss = s;
  484.         p1 = s;
  485.     } else {
  486.         *p2 = savechar;
  487.         if (*p2 == 0) return NULL;
  488.         p1 = p2+1;
  489.     } 
  490.     for (p=p1; *p != 0; p++) {  /* find a non space */
  491.         if (term_table[*p]==false) break;
  492.     }   
  493.     if (*p==0) return NULL; 
  494.     p1 = p;
  495.     if (*p=='"') {
  496.         p2 = strchr(p+1,'"');
  497.         if (p2==NULL) p2 = p;
  498.         p = ++p2;
  499.     } else {
  500.         for (; *p != 0; p++) {  /* find next space */
  501.             if (term_table[*p]==true) break;
  502.         }
  503.     }
  504.     p2 = p;
  505.     savechar = *p2;
  506.     *p2 = 0;
  507.     return p1;
  508. }
  509.  
  510.  
  511. cmd_load_list(RANGE *r, char *inbuff)
  512. {
  513.     char *s;
  514.     s = m_tokend(inbuff);
  515.     for (;s!=NULL;) {
  516.         load_str(r->col,r->row,s);
  517.         s = m_tokend(NULL);
  518.         range_next(r);
  519.     }
  520.  
  521. }
  522. cmd_load_line(int x, int y, char *inbuff)
  523. {
  524.     char *s;
  525.     s = m_tokend(inbuff);
  526.     for (;s!=NULL;) {
  527.         load_str(x,y,s);
  528.         s = m_tokend(NULL);
  529.         x++;
  530.     }
  531.  
  532. }
  533. load_str(int x, int y, char *s)
  534. {
  535.     static char bb[88];
  536.     if (strcmp(s,".")==0 || strcmp(s,"-")==0 || strcmp(s,"*")==0) clear_cell(x,y);
  537.     else if (isdigit(*s) || *s=='-' || *s=='+' || *s=='.') set_cell(x,y,atof(s));
  538.     else {
  539.         if (strlen(s)>80) {
  540.             strncpy(bb,s,80);
  541.             bb[80] = 0;
  542.             set_scell(x,y,bb);
  543.         } else set_scell(x,y,s);
  544.     }
  545.     show_ifcell(x,y);
  546. }
  547. cmd_save(char *fname, char *range, char *format, int ntok)
  548. {
  549.     RANGE rr;
  550.     static char inbuff[2001];
  551.     static char fmtg[80],buff1[80],savefmtg[80];
  552.     FILE *fptr;
  553.     int lcount=0;
  554.     int i,inlen=0,thelot,k;
  555.     double v;
  556.     char *s;
  557.  
  558.     strlwr(fname);
  559.     trim_data();
  560.     thelot = false;
  561.     if (*range=='-') {s = range; range = format; format = s;}
  562.     if (strcmp(format,"-COMMA")==0) {
  563.         set_outwidth(0);
  564.         between = strdup(", ");
  565.     }
  566.     if (strcmp(format,"-TAB")==0) {
  567.         set_outwidth(0);
  568.         between = strdup("\t");
  569.     }
  570.     if (strcmp(format,"-SPACE")==0) {
  571.         set_outwidth(0);
  572.         between = strdup(" ");
  573.     }
  574.  
  575.     sprintf(fmtg,"%%.%dg",outwidth2);
  576.     if (outwidth1==0 && outwidth2==0) strcpy(fmtg,"%g");
  577.     strcpy(savefmtg,fmtg);
  578.  
  579.     if (ntok<2) fname = file_name;
  580.     if (strcmp(fname,"*")==0) fname = file_name;
  581.     strcpy(file_name,fname);
  582.  
  583.     /* format strings   "%2.3f, " */
  584.     if (ntok<4) format = "%g ";
  585.     if (ntok<3 || strcmp(range," ")==0) thelot = true;
  586.     if (thelot) range = "C1R1";
  587.     if (range_def(range,&rr)) ;
  588.     else  {                 /* range = exp */
  589.         fner("Invalid range given (%s)%d \n",range,strlen(range));
  590.         return;
  591.     }
  592.     if (thelot) rr.c2 = max_x;
  593.     unlink("manip_.bak");
  594.     unlink("manip_.tmp");
  595.     fptr = fopen("manip_.tmp","w");
  596.     if (fptr==NULL) {
  597.         fner("Could not open (%s) \n",fname);
  598.         return;
  599.     }
  600.     for (;range_next(&rr);) {
  601.         if (new_line==true) {
  602.             if (fprintf(fptr,"%s\n",inbuff) <0) printf("Error writing output file\n");
  603.             inbuff[50] = 0;
  604.             if (++lcount==1) fner("{%s} W=%d D=%d {%s}",fname,outwidth1,outwidth2,inbuff);
  605.             inlen = 0;
  606.         }
  607.         if (inlen>0) { strcpy(inbuff+inlen,between); inlen +=strlen(between);}
  608.         get_cellboth(rr.col,rr.row,&v,&s);
  609.         k = rr.col;
  610.         if (k>199) k = 199;
  611.         if (coltype[k]==0) strcpy(fmtg,savefmtg);
  612.         if (coltype[k]==1) strcpy(fmtg,"%f");
  613.         if (coltype[k]==2) strcpy(fmtg,"%e");
  614.         if (s==NULL) {
  615.             i = sprintf(buff1,fmtg,vcell(rr.col,rr.row));
  616.             if (dpoints[k]>0) i = strcpydecimal(inbuff+inlen,buff1,outwidth1,dpoints[k]);
  617.             else i = strcpywidth(inbuff+inlen,buff1,outwidth1);
  618.         } else {
  619.             i = strcpywidth(inbuff+inlen,s,outwidth1);
  620.         }
  621.         inlen += i;
  622.     }
  623.     if (new_line==true) {
  624.         if (fprintf(fptr,"%s\n",inbuff)<0) {
  625.             fner("Error writing output file"); 
  626.             return;
  627.         }
  628.         inbuff[50] = 0;
  629.         if (++lcount==1) fner("Width=%d Precision=%d {%s}",outwidth1,outwidth2,inbuff);
  630.         inlen = 0;
  631.     }
  632.     fclose(fptr);
  633.     if (rename(fname,"manip_.bak")!=0);
  634.     if (rename("manip_.tmp",fname)!=0) fner("Unable to rename manip_.tmp");
  635. }
  636. strcpydecimal(char *dest, char *src, int wid, int dpoints)
  637. {
  638.     /* 123 ,  12.031,  0.0003321 */
  639.     /* dpoints 2 goes too   */
  640.     /* 123.00  12.03  0.00  */
  641.     static char buff[80];
  642.     int i;
  643.  
  644.     strcpy(buff,src);
  645.     if (strchr(buff,'.')==NULL) strcat(buff,".");
  646.     strcat(buff,"0000000000000000000000000000000000");
  647.     *(strchr(buff,'.')+dpoints+1) = 0;
  648.     strcpywidth(dest,buff,wid);
  649.     return strlen(dest);
  650. }
  651. strcpywidth(char *dest, char *src, int wid)
  652. {
  653.     static char buff[80];
  654.     int i;
  655.     i = wid-strlen(src);
  656.     if (i<0) i = 0;
  657.     memset(buff,' ',i);
  658.     buff[i] = 0;
  659.     strcpy(dest,buff);
  660.     strcat(dest,src);
  661.     return strlen(dest);
  662. }
  663. set_outwidth(char *s)
  664. {
  665.     char *ss;
  666.     ss = strchr(s,'.');
  667.     if (ss==NULL) {
  668.         outwidth1 = atoi(s);
  669.         outwidth2 = 8;
  670.     } else {
  671.         *ss++ = 0;
  672.         outwidth1 = atoi(s);
  673.         outwidth2 = atoi(ss);
  674.     }
  675. }
  676. char *unquote(char *s)
  677. {
  678.     char ss[80];
  679.     strcpy(ss,s);
  680.     if (*s=='"') {
  681.     ss[strlen(ss)-1] = 0;
  682.     return strdup(ss+1);
  683.     } else return strdup(ss);
  684. }
  685. cmd_copy(char *src, char *dest, char *ifexp, int ntok, int always)
  686. {
  687.     RANGE ss,dd,savess;
  688.     int c_idx[20], c_val[20], nc, j, isif=false;
  689.     int r_idx[20], r_val[20], nr;
  690.     int cp,vtype,vidx,ddok,ssok;
  691.     double v;
  692.     char outstr[30];
  693.     int32 pcode[200];
  694.     int plen;
  695.     vtype = 1;
  696.  
  697.     if (ntok>4) isif = true;
  698.     if (!range_def(src,&ss)) { fner("Error in source range {%s} \n",src); return;}
  699.     if (!range_def(dest,&dd)) { fner("Error in destination range {%s} \n",dest); return;}
  700.  
  701.     if (isif) {
  702.         polish(ifexp,(char *) pcode,&plen,&vtype);
  703.         var_find_rc(c_idx,c_val,&nc,'C');
  704.         var_find_rc(r_idx,r_val,&nr,'R');
  705.     }
  706.     ddok = range_next(&dd);
  707.     ssok = range_next(&ss);
  708.     savess = ss;
  709.     for (;ssok && ddok;) {
  710.         if (isif) {
  711.             cp = 0;
  712.             eval_setxy(ss.col,ss.row);
  713.             eval_setxyd(dd.col,dd.row);
  714.             for (j=0;j<nc;j++) {
  715.                 var_set(c_idx[j],vcell(c_val[j],ss.row));
  716.             }
  717.             for (j=0;j<nr;j++) {
  718.                 var_set(r_idx[j],vcell(ss.col,r_val[j]));
  719.             }
  720.             eval(pcode,&cp,&v,outstr,&vtype);
  721.         }
  722.         if (v==true || !isif) {
  723.             copy_cell(ss.col,ss.row,dd.col,dd.row);
  724.             show_ifcell(dd.col,dd.row);
  725.             ddok = range_next(&dd);
  726.         } else if (always) ddok = range_next(&dd);
  727.         if (always!=2) ddok = true;
  728.         ssok = range_next(&ss);
  729.         if (!ssok && always==2) {
  730.             ss = savess;    ssok = true;
  731.         }
  732.     }
  733. }
  734. int gen_next(char *pat, double *v);
  735. cmd_generate(char *patx, char *dest, int ntok)
  736. {
  737.     int left,right;
  738.     RANGE rr;
  739.     static char pat[188];
  740.     static char middle[80];
  741.     double v;
  742.     int i,j;
  743.  
  744.     strcpy(pat,patx);
  745.     if (strchr(pat,'(')==NULL) {fner("Expecting left bracket"); return;}
  746.     if (strchr(pat,')')==NULL) {fner("Expecting left bracket"); return;}
  747.     if (ntok!=3) {fner("Expecting (GEN pattern range)"); return;}
  748.  
  749.     if (pat[0]=='(') {strcpy(pat,"1"); strcat(pat,patx);}
  750.     if (pat[strlen(pat)-1] == ')') strcat(pat,"1");
  751.     left = atoi(strtok(pat,"()"));
  752.     strcpy(middle,strtok(NULL,"()"));
  753.     right = atoi(strtok(NULL,"()"));
  754.     if (left==0) left = 1;
  755.     if (right==0) right = 1;
  756.     if (!range_def(dest,&rr))  {fner("Invalid range given (%s) \n",dest); return;}
  757.     for (i=0;i<right;i++) {
  758.       gen_next(middle,&v);
  759.       for (;gen_next(NULL,&v);) {
  760.         for (j=0;j<left;j++) {
  761.         range_next(&rr);
  762.         set_cell(rr.col,rr.row,v);
  763.         show_ifcell(rr.col,rr.row);
  764.         }
  765.       }
  766.     }
  767. }
  768. gen_next(char *pat, double *v)
  769. {
  770.     static char *s,p[200];
  771.     static double v1,v2,v3;
  772.     static int instep;
  773.     char *c1,*c2;
  774.     if (pat!=NULL) {
  775.         strcpy(p,pat);
  776.         s = strtok(p,",");
  777.         return true;
  778.     }
  779.     if (instep) {
  780.            v1 += v3;
  781.            *v = v1;
  782.            if (v1<=v2) return true;
  783.            else instep = false;
  784.     }
  785.     if (s==NULL) return false;
  786.     c2 = c1 = strchr(s,':');
  787.     if (c1!=NULL) c2 = strchr(c1+1,':');
  788.  
  789.     if (c1==NULL) {
  790.         *v = atof(s);
  791.         s = strtok(NULL,",");
  792.         return true;
  793.     }
  794.     v1 = atof(s);
  795.     v2 = atof(c1+1);
  796.     if (c2==NULL) v3 = 1; else v3 = atof(c2+1);
  797.     *v = v1;
  798.     instep = true;
  799.     s = strtok(NULL,",");
  800.     if (v1>v2) return false;
  801.     return true;
  802. }
  803. int c_idx[20], c_val[20], ncc;
  804. int r_idx[20], r_val[20], nrr;
  805. int32 cpcode[200];
  806. cmd_polish(char *exp)
  807. {
  808.     int cp,vtype,vidx,ddok,ssok;
  809.     int plen;
  810.     vtype = 1;
  811.  
  812.     polish(exp,(char *) cpcode,&plen,&vtype);
  813.     var_find_rc(c_idx,c_val,&ncc,'C');
  814.     var_find_rc(r_idx,r_val,&nrr,'R');
  815. }
  816. cmd_eval(int x1, int y1, double *v)
  817. {
  818.     int cp,vtype,vidx,ddok,ssok,j;
  819.     char outstr[30];
  820.     vtype = 1;
  821.  
  822.     cp = 0;
  823.     eval_setxy(x1,y1);
  824.     eval_setxyd(x1,y1);
  825.     for (j=0;j<ncc;j++) {
  826.         var_set(c_idx[j],vcell(c_val[j],y1));
  827.     }
  828.     for (j=0;j<nrr;j++) {
  829.         var_set(r_idx[j],vcell(x1,r_val[j]));
  830.     }
  831.     eval(cpcode,&cp,v,outstr,&vtype);
  832. }
  833. cmd_delete(char *range, char *ifexp, int ntok)
  834. {
  835.     RANGE rr;
  836.     double v;
  837.     int isif,i,j,wid,w;
  838.     if (ntok>2) isif = true; else isif = false;
  839.     if (!range_def(range,&rr)) { fner("Error in range {%s} \n",range); return;}
  840.  
  841.     if (isif) cmd_polish(ifexp);
  842.     range_next(&rr);
  843.     if (rr.colfirst) {
  844.         w = rr.c2-rr.c1+1;
  845.         wid = max_x-rr.c1;
  846.     } else {
  847.         w = rr.r2-rr.r1+1;
  848.         wid = max_y-rr.r1;
  849.     }
  850.     for (;;) {
  851.         if (rr.colfirst) {
  852.           if (isif) cmd_eval(rr.col,rr.row,&v);
  853.           if (v==true || !isif) {
  854.             for (j=0;j<wid; j++) {
  855.               copy_cell(rr.col+j+w,rr.row,rr.col+j,rr.row);
  856.               show_ifcell(rr.col+j,rr.row);
  857.             }
  858.             for (j=0;j<w;j++) {
  859.               clear_cell(rr.c2+wid-j,rr.row);
  860.               show_ifcell(rr.c2+wid-j,rr.row);
  861.             }
  862.           }
  863.           rr.row++;
  864.           if (rr.row>rr.r2) break;
  865.         } else {
  866.           if (isif) cmd_eval(rr.col,rr.row,&v);
  867.           if (v==true || !isif) {
  868.             for (j=0;j<wid; j++) {
  869.               copy_cell(rr.col,rr.row+j+w,rr.col,rr.row+j);
  870.               show_ifcell(rr.col,rr.row+j);
  871.             }
  872.             for (j=0;j<w;j++) {
  873.               clear_cell(rr.col,rr.r2+wid-j);
  874.               show_ifcell(rr.col,rr.r2+wid-j);
  875.             }
  876.           }
  877.           rr.col++;
  878.           if (rr.col>rr.c2) break;
  879.         }
  880.     }
  881. }
  882. int oncol;
  883. cmd_sort(char *range, char *ifexp, int ntok)
  884. {
  885.     RANGE rr;
  886.     double v;
  887.     int *pnt;
  888.     int isif,i,j,wid,w,c,savemax;
  889.     if (ntok<3) {fner("Expecting   SORT  c1c2  ON <exp> "); return; }
  890.     if (!range_def(range,&rr)) { fner("Error in range {%s} \n",range); return;}
  891.  
  892.     savemax = max_x;
  893.     oncol = max_x + 1;
  894.     cmd_polish(ifexp);
  895.     range_next(&rr);
  896.     if (ntok==5) {
  897.       for (i=rr.r1;i<=rr.r2;i++) {
  898.         copy_cell(rr.c1,i,oncol,i);
  899.       }
  900.     } else {
  901.       for (i=rr.r1;i<=rr.r2;i++) {
  902.         cmd_eval(rr.c1,i,&v);
  903.         set_cell(oncol,i,v);
  904.       }
  905.     }
  906.     pnt = calloc(max_y+2,sizeof(int));
  907.     if (pnt==NULL) {fner("Not enough memory to sort"); return;}
  908.     for (i=0;i<=max_y+1;i++) pnt[i] = i;
  909.     for (i=rr.r1+1;i<=rr.r2;i++) {
  910.         if (cell_greater(oncol,pnt[i-1],oncol,pnt[i])) {
  911.             sort_shuffle(i,rr.r1,pnt);
  912.         }
  913.     }
  914.     for (c=rr.c1; c<=rr.c2; c++) {
  915.         for (j=rr.r1;j<=rr.r2;j++) {
  916.             copy_cell(c,pnt[j],oncol,j);
  917.         }
  918.         for (j=rr.r1;j<=rr.r2;j++) {
  919.             copy_cell(oncol,j,c,j);
  920.             show_ifcell(c,j);
  921.         }
  922.     }
  923.     for (j=1;j<=max_y;j++) clear_cell(oncol,j);
  924.     max_x = savemax;
  925. }
  926. sort_shuffle(int i, int r1, int *pnt)
  927. {
  928.     int ins,j,x;
  929.     ins = r1;
  930.     for (j=i-1;j>=r1;j--) {
  931.         if (cell_greater(oncol,pnt[i],oncol,pnt[j])) {
  932.             ins = j + 1;
  933.             break;
  934.         }
  935.     }
  936.     x = pnt[i];
  937.     for (j=i;j>=ins;j--) pnt[j] = pnt[j-1];
  938.     pnt[ins] = x;
  939. }
  940. cmd_insert(char *range)
  941. {
  942.     RANGE rr;
  943.     double v;
  944.     int isif,i,j,wid,w,cwid,cw,rwid,rw;
  945.     if (!range_def(range,&rr)) { fner("Error in range {%s} \n",range); return;}
  946.  
  947.     range_next(&rr);
  948.     cw = rr.c2-rr.c1+1;
  949.     cwid = max_x-rr.c1+1;
  950.     rw = rr.r2-rr.r1+1;
  951.     rwid = max_y-rr.r1+1;
  952.     for (;;) {
  953.         if (rr.colfirst) {
  954.             for (j=cwid-1;j>=0; j--) {
  955.               copy_cell(rr.col+j,rr.row,rr.col+j+cw,rr.row);
  956.               show_ifcell(rr.col+j+cw,rr.row);
  957.             }
  958.             for (j=0;j<cw;j++) {
  959.               clear_cell(rr.c1+j,rr.row);
  960.               show_ifcell(rr.c1+j,rr.row);
  961.             }
  962.             rr.row++;
  963.             if (rr.row>rr.r2) break;
  964.         } else {
  965.             for (j=rwid-1;j>=0; j--) {
  966.               copy_cell(rr.col,rr.row+j,rr.col,rr.row+j+rw);
  967.               show_ifcell(rr.col,rr.row+j+rw);
  968.             }
  969.             for (j=0;j<rw;j++) {
  970.               clear_cell(rr.col,rr.r1+j);
  971.               show_ifcell(rr.col,rr.r1+j);
  972.             }
  973.             rr.col++;
  974.             if (rr.col>rr.c2) break;
  975.         }
  976.     }
  977. }
  978. cmd_data(char *range)
  979. {
  980.     RANGE rr;
  981.     static char ans[155];
  982.     int cmd;
  983.     if (!range_def(range,&rr)) {
  984.         fner("Invalid range given (%s)%d \n",range,strlen(range));
  985.         return;
  986.     }
  987.     for (;;) {
  988.         range_next(&rr);
  989.         mjl_flush();
  990. xxx:        set_newxy(rr.col,rr.row);
  991.         if (!iserr) fner("Press ^Z or ESC when data entry finished\n");
  992.         read_command(&cmd,ans,"DATA% ");
  993.         if (cmd==eescape || cmd==equit) break;
  994.         if (cmd!=0) {
  995.             do_arrow(cmd);
  996.             rr.col = curx; rr.row = cury;
  997.             goto xxx;
  998.         } else {
  999.           if (isnumber(ans)) {
  1000.             set_cell(curx,cury,atof(ans));
  1001.           } else {
  1002.             set_scell(curx,cury,ans);
  1003.           }
  1004.           show_cellwide(curx,cury);
  1005.         }
  1006.     }
  1007. }
  1008. swap_def(char *s, RANGE *r)
  1009. {
  1010.     char *s1;
  1011.     char rr,cc;
  1012.  
  1013.     strip_colon(s);
  1014.  
  1015.     r->c1 = r->c2 = r->r1 = r->r2 = r->row = r->col = 0;
  1016.  
  1017.     if (*s=='C') {cc='C'; rr='R'; r->colfirst = true;}
  1018.     else if (*s=='R') {cc='R'; rr='C'; r->colfirst = false;}
  1019.     else return false;
  1020. /*  c1   c1r1r10   c3c4r7 c3r7  c3c4r1r2 |   r1r2c1c3   c3r7  r2*/
  1021.  
  1022.     s1 = range_int(s,&(r->c1));
  1023.     if (*s1==cc) {
  1024.         s1 = range_int(s1,&r->c2);
  1025.     }
  1026.     if (*s1==rr) {
  1027.         s1 = range_int(s1,&r->r1);
  1028.         if (*s1==cc) {
  1029.             s1 = range_int(s1,&r->c2);
  1030.         }
  1031.         if (*s1==rr) {
  1032.             s1 = range_int(s1,&r->r2);
  1033.         }
  1034.         if (*s1==cc) {
  1035.             s1 = range_int(s1,&r->c2);
  1036.         }
  1037.     }
  1038.     if (!r->colfirst) {
  1039.         swapint(&r->c1,&r->r1);
  1040.         swapint(&r->c2,&r->r2);
  1041.     }
  1042.     if (*s1!=0) return false;
  1043.     return true;
  1044. }
  1045. cmd_swap(char *range)
  1046. {
  1047.     RANGE rr;
  1048.     int i,j;
  1049.     if (!swap_def(range,&rr)) {
  1050.         fner("Invalid range given (%s) expecting c1c2 or r1r2 \n",range);
  1051.         return;
  1052.     }
  1053.     if (rr.colfirst) {
  1054.       j = max_y;
  1055.       if (rr.r2!=0) j = rr.r2;
  1056.       if (rr.c1==0 || rr.c2==0) {fner("Invalid range, expected c1c2\n"); return;}
  1057.       for (i=1;i<=max_y;i++) {
  1058.         swap_cell(rr.c1,i,rr.c2,i);
  1059.         show_ifcell(rr.c1,i); show_ifcell(rr.c2,i);
  1060.       }
  1061.     } else {
  1062.       j = max_x;
  1063.       if (rr.c2!=0) j = rr.c2;
  1064.       if (rr.r1==0 || rr.r2==0) {fner("Invalid range, expected r1r2\n"); return;}
  1065.       for (i=1;i<=max_x;i++) {
  1066.         swap_cell(i,rr.r1,i,rr.r2);
  1067.         show_ifcell(i,rr.r1); show_ifcell(i,rr.r2);
  1068.       }
  1069.     }
  1070. }
  1071. int add_dotman(char *s);
  1072. FILE *logfile;
  1073. log_open(char *fname)
  1074. {
  1075.     add_dotman(fname);
  1076.     strlwr(fname);
  1077.     logfile = fopen(fname,"w");
  1078.     if (logfile==NULL) {
  1079.         fner("Could not open (%s) \n",fname);
  1080.         return;
  1081.     }
  1082.     islogging = true;
  1083. }
  1084. log_write(char *s)
  1085. {
  1086.     fprintf(logfile,"%s\n",s);
  1087. }
  1088. log_close()
  1089. {
  1090.     if (islogging) fclose(logfile);
  1091.     islogging = false;
  1092. }
  1093. add_dotman(char *s)
  1094. {
  1095.     if (strstr(s,".")==0) strcat(s,".man");
  1096. }
  1097. FILE *atfile;
  1098. at_open(char *fname)
  1099. {
  1100.     add_dotman(fname);
  1101.     strlwr(fname);
  1102.     atfile = fopen(fname,"r");
  1103.     if (atfile==NULL) {
  1104.         fner("Could not open (%s) \n",fname);
  1105.         return;
  1106.     }
  1107.     isating = true;
  1108. }
  1109. at_read(char *s)
  1110. {
  1111.     s[0] = 0;
  1112.     if (feof(atfile)) {
  1113.         fclose(atfile); atfile = NULL; isating = false; return false;
  1114.     }
  1115.     s[0] = 0;
  1116.     if (fgets(s,200,atfile)==NULL) return false;
  1117.     return true;
  1118. }
  1119. strip_colon(char *s)
  1120. {
  1121.     char *ss;
  1122.     ss = s;
  1123.     for (;*s!=0;s++) {
  1124.         if (*s!=':') *ss++ = *s;
  1125.     }
  1126.     *ss++ = 0;
  1127. }
  1128. cmd_parsum(char *range, char *dest)
  1129. {
  1130.     RANGE rr,dd;
  1131.     double total=0;
  1132.     if (!range_def(range,&rr)) { fner("Invalid range given (%s) \n",range); return;}
  1133.     if (!range_def(dest,&dd)) { fner("Invalid destination given (%s) \n",range); return;}
  1134.     for (;range_next(&rr);) {
  1135.         range_next(&dd);
  1136.         total = total + vcell(rr.col,rr.row);
  1137.         set_cell(dd.col,dd.row,total);
  1138.         show_ifcell(dd.col,dd.row);
  1139.     }
  1140. }
  1141. int rangestd(RANGE *rr, double mean, int32 numrow, double *variance,
  1142.     double *stddev);
  1143.  
  1144. cmd_sum(char *range)
  1145. {
  1146.     RANGE rr,rrsave;
  1147.     double v,var,stddev;
  1148.     char *s;
  1149.     double total=0;
  1150.     int32 ntot=0;
  1151.     if (!range_def(range,&rr)) { fner("Invalid range given (%s) \n",range); return;}
  1152.     rrsave = rr;
  1153.     for (;range_next(&rr);) {
  1154.         get_cellboth(rr.col,rr.row,&v,&s);
  1155.         if (s==NULL) {
  1156.             total = total + v;
  1157.             ntot++;
  1158.         }
  1159.     }
  1160.     if (ntot>0) {
  1161.         rangestd(&rrsave,total/ntot,ntot,&var,&stddev);
  1162.         printmess("Total %g, Avg %g, sd %g, var %g, Cells %ld \n",total,total/ntot,stddev,var,ntot);
  1163.     } else fner("No values in range\n");
  1164. }
  1165. rangestd(RANGE *rr, double mean, int32 numrow, double *variance,
  1166.     double *stddev)
  1167. {
  1168.    int i;
  1169.    char *s;
  1170.    double xsqr,v;
  1171.  
  1172.    xsqr = 0.0;
  1173.    if (numrow<2) return;
  1174.    for (;range_next(rr);) {
  1175.       get_cellboth(rr->col,rr->row,&v,&s);
  1176.       if (s==NULL) {
  1177.     xsqr = xsqr + v*v;
  1178.       }
  1179.    }
  1180.    (*variance) = (xsqr - numrow * mean*mean) / (numrow - 1);
  1181.    (*stddev) = sqrt(fabs((*variance)));
  1182. }
  1183.  
  1184. cmd_clear(char *range)
  1185. {
  1186.     RANGE rr;
  1187.     if (!range_def(range,&rr)) { fner("Invalid range given (%s) \n",range); return;}
  1188.     for (;range_next(&rr);) {
  1189.         clear_cell(rr.col,rr.row);
  1190.         show_ifcell(rr.col,rr.row);
  1191.     }
  1192. }
  1193. int fitlsq(RANGE *rrr,int ndata, double *a, double *b, double *siga, double *sigb, double *chi2, double *q);
  1194. cmd_fit(char *range)
  1195. {
  1196.     RANGE rr,rrsave;
  1197.     char *s;
  1198.     double v,a,b,siga,sigb,chi2,q;
  1199.     double total=0;
  1200.     int ntot=0;
  1201.     if (!range_def(range,&rr)) { fner("Invalid range given (%s) \n",range); return;}
  1202.     rr.c2 = rr.c1;
  1203.     rrsave = rr;
  1204.     for (;range_next(&rr);) {
  1205.         get_cellboth(rr.col,rr.row,&v,&s);
  1206.         if (s==NULL) {
  1207.             ntot++;
  1208.         }
  1209.     }
  1210.     if (ntot>0) {
  1211.       fitlsq(&rrsave,ntot,&a,&b,&siga,&sigb,&chi2,&q);
  1212.       printmess("y = %g + b*%g    siga=%g sigb=%g  chi2=%g\n"
  1213.         ,a,b,siga,sigb,chi2);
  1214.     } else fner("No values in range\n");
  1215. }
  1216. static double sqrarg;
  1217. #define SQR(a) (sqrarg=(a),sqrarg*sqrarg)
  1218. fitlsq(RANGE *rrr,int ndata, double *a, double *b, double *siga, double *sigb, double *chi2, double *q)
  1219. {
  1220.     RANGE  rr;
  1221.     double v,x,y,sx=0,sy=0,st2=0,wt,t,ss,sigdat,sxoss;
  1222.     char *s;
  1223.     *b = 0.0;
  1224.     for (rr = *rrr;range_next(&rr);) {
  1225.         get_cellboth(rr.col,rr.row,&x,&s);
  1226.         get_cellboth(rr.col+1,rr.row,&y,&s);
  1227.         if (s==NULL) {
  1228.             sx += x;
  1229.             sy += y;
  1230.         }
  1231.     }
  1232.     ss = ndata;
  1233.     sxoss = sx/ss;
  1234.     for (rr = *rrr;range_next(&rr);) {
  1235.         get_cellboth(rr.col,rr.row,&x,&s);
  1236.         get_cellboth(rr.col+1,rr.row,&y,&s);
  1237.         if (s==NULL) {
  1238.             t=x-sxoss;
  1239.             st2 += t*t;
  1240.             *b += t*y;
  1241.         }
  1242.     }
  1243.     *b /= st2;
  1244.     *a = (sy-sx*(*b))/ss;
  1245.     *siga = sqrt((1.0+sx*sx/(ss*st2))/ss);
  1246.     *sigb = sqrt(1.0/st2);
  1247.     *chi2=0.0;
  1248.     for (rr = *rrr;range_next(&rr);) {
  1249.         get_cellboth(rr.col,rr.row,&x,&s);
  1250.         get_cellboth(rr.col+1,rr.row,&y,&s);
  1251.         if (s==NULL) {
  1252.             *chi2 += SQR(y-(*a)-(*b)*x);
  1253.         }
  1254.     }
  1255.     *q = 1.0;
  1256.     sigdat = sqrt((*chi2)/(ndata-2));
  1257.     *siga *= sigdat;
  1258.     *sigb *= sigdat;
  1259. }
  1260.